/*
    Copyright 2006 Andrew Wilkinson <andrew@indiegigs.co.uk>

    This file is part of libgp2x.

    libgp2x is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    libgp2x is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with libgp2x; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "gp2x_internal.h"

int main();

void GP2x_init(int init) {
    asm volatile (
    // set up memory region 0 -- the whole 4GB address space, uncached
    // bit 0 = enable
    // bits 1-5: 5-bit region size (N).  Size = 2^(N+1).  For this partition, set all bits for maximum size
    // bits 12:31: base address.  Both regions in this example have a base address of zero
    "mov r0, #0x3F                 @ region data \n"
    "mcr p15, 0, r0, c6, c0, 0     @ data region 0 \n"
    "mcr p15, 0, r0, c6, c0, 1     @ code region 0 \n"
    // set up region 1 which is the first 16 megabytes.
    // bit 0 = enable
    // bits 1-5: as above.  16 MB is 2^24 so N should be 23.  In hex, 23 is 0x17.
    // (0x17<<1) | 1 = 0x2F
    "mov r0, #0x2F\n"             // region data
    "mcr p15, 0, r0, c6, c1, 0\n" // data region 1
    "mcr p15, 0, r0, c6, c1, 1\n" // code region 1
    // set region 1 to be cacheable (so the first 16M will be cacheable)
    "mov r0, #2\n"                // 2 means region 1 (1 would have meant region 0, 4 would mean region 2, etc)
    "mcr p15, 0, r0, c2, c0, 0\n" // turn on data cache
    "mcr p15, 0, r0, c2, c0, 1\n" // turn on instruction cache
    // set region 1 to be bufferable too (only data)
    "mcr p15, 0, r0, c3, c0, 0\n" // turn on write buffer
    // set protection on for all regions
    "mov r0, #15\n"               // more than we actually need
    "mcr p15, 0, r0, c5, c0, 0\n" // set full data permission
    "mcr p15, 0, r0, c5, c0, 1\n" // set full code permission
    "mrc p15, 0, r0, c1, c0, 0\n" // fetch current control reg
    "orr r0, r0, #1\n"            // 0x00000001: enable protection unit
    "orr r0, r0, #4\n"            // 0x00000004: enable D cache
    "orr r0, r0, #0x1000\n"       // 0x00001000: enable I cache
    "orr r0, r0, #0xC0000000\n"   //  0xC0000000: async+fastbus
    "mcr p15, 0, r0, c1, c0, 0\n" // set control reg
    );

    GP2x_registers = (unsigned short*)(0xc0000000 - GP2x_940_OFFSET);

    GP2x_upper_memory_init(16*1024*1024, 16*1024*1024);
    GP2x_video_init();
    GP2x_message_init();
    GP2x_input_init();

    main();
}
